package model.searchers;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import model.parseTree.SyntaxTree;
import model.searchers.linkedListSearcher.LinkedList;

/**
 * Class GenericSearcher represents generic functions used by all or more than one searcher.
 * The class is abstract to prevent it from being created directly but only used by subclasses.
 */

public abstract class GenericSearcher implements ISearcher {

	private boolean booleanSearch;
	private int totalWordCount = 0;
	private String fileName;
	
	/** 
	 * General method used in all subclasses when reading data from a file
	 * 
	 * @param 	fileName	The path to the file
	 * @return	infile		Returns a BufferedReader object
	 */
	public BufferedReader getDataFromFile(String fileName) {
		// Make File object to get path of argument filename
		File newfile = new File(fileName);
		this.setFileName(newfile.getAbsolutePath());
		// Initializing infile
		BufferedReader infile = null;

		// Open the file given as argument and test if it is valid
		try {
			infile = new BufferedReader(new FileReader(newfile));
			
		} catch (Exception e) {
			System.out.println("\nThe location to the data file is not valid!");
			System.out.println("Enter the local path of the file you wish to search in correctly.");
			System.out.println("For instance: C:\\java\\cluster\\itcwww-medium.txt or relatively data/itcwww-medium.txt");
			e.printStackTrace();
			System.exit(0);
		}
		return infile;
	}
	/**
	 * Gets the result and transforms it into a String array. Checks if boolean search is enabled.
	 * @param 	key		The search word
	 * @return	result 	Returns a String array with the result
	 */
	// This method returns a search result formatted for end user presentation
	@Override
	public String[] getFormattedResult(String key) {
		LinkedList structuredResult;
		if (isBooleanSearch()) {
			SyntaxTree tree = new SyntaxTree(key);
			structuredResult = tree.readTree(this);
		} else {
			structuredResult = this.get(key);
		}
		String[] result = this.formatResult(structuredResult);
		return result;
	}

	/**
	 * An abstract method to force the creation of formatResult methods in all subclasses
	 * @param l linked list
	 * @return	a String array
	 */
	public abstract String[] formatResult(LinkedList l);

	/**
	 * Sets whether the search should handle boolean search or not
	 * @param mode	A boolean. True = enable boolean search
	 */
	public void setBooleanSearch(boolean mode) {
		this.booleanSearch = mode;
	}
	
	/**
	 * Increments the count of words
	 */
	public void incrementTotalWordCount() {
		totalWordCount++;
	}
	
	/**
	 * Get the count of total number of words
	 * @return totalWordCount integer
	 */
	public int getTotalWordCount() {
		return totalWordCount;
	}
	
	/**
	 * Returns the value of boolean search
	 * @return booleanSearch
	 */
	public boolean isBooleanSearch() {
		return booleanSearch;
	}
	private void setFileName(String fileName) {
		this.fileName = fileName;
	}
	public String getFileName() {
		return fileName;
	}
	
	public String getSearcherType() {
		return this.getClass().getName();
	}

}
